package com.woniuxy.woniubook.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.woniuxy.woniubook.entity.Book;
import com.woniuxy.woniubook.entity.Item;
import com.woniuxy.woniubook.entity.Order;
import com.woniuxy.woniubook.entity.User;
import com.woniuxy.woniubook.mapper.BookMapper;
import com.woniuxy.woniubook.mapper.ItemMapper;
import com.woniuxy.woniubook.mapper.OrderMapper;
import com.woniuxy.woniubook.service.BookService;
import com.woniuxy.woniubook.service.CartService;
import com.woniuxy.woniubook.service.OrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniuxy.woniubook.vo.CartItemVo;
import com.woniuxy.woniubook.vo.CartVo;
import com.woniuxy.woniubook.vo.OrderVo;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author wugd
 * @since 2022-11-16 02:13:11
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Autowired
    CartService cartService ;

    @Autowired
    OrderMapper orderMapper;
    @Autowired
    BookService bookService ;

    @Autowired
    BookMapper bookMapper ;

    @Autowired
    ItemMapper itemMapper ;

    @Autowired
    RabbitTemplate rabbitTemplate ;

    @Autowired
    RedisTemplate<String,Object> redisTemplate ;

    /*
        Spring中声明式事务，什么情况下会失效 ？
        Spring声明式事务实现原理是什么 ？   动态代理 + 反射  ---> 基于SpringAop编程实现
        （1）、开启事务
        （2）、提交事务
        （3）、回滚事务
        1. 逻辑方法没有抛出异常（框架或者 jdk api 抛的异常   手动抛异常）
        2. 在一个非事务方法中 调用了一个本类中的事务方法
        3. 方法不是public的

     */

    public  String test(User user, Long addressId, Long[] bookIds){
        return  this.addOrder(user,addressId,bookIds);
    }

    @Override
    @Transactional
    public String addOrder(User user, Long addressId, Long[] bookIds) {
        //开启事务    前置通知
        //1. 插入订单
        Order order = new Order();
        String orderNum = "WONIU"+System.currentTimeMillis();
        order.setOrderNum(orderNum);
        order.setUserId(user.getId());
        order.setAddressId(addressId);
        order.setCreatetime(new Date());
        order.setState(1);  // 1.未支付  2 . 已支付  3.退款中  4. 已退款  5.已取消
        CartVo cartVo = cartService.getMyCart(user.getId());
        BigDecimal all = new BigDecimal("0.0") ;
        List<CartItemVo> carts = cartVo.getCarts();
        List<CartItemVo> buyCartItemVoList = new ArrayList<>();  //已经购买的商品明细
        for (CartItemVo cv :carts) {
            for (Long id : bookIds) {
                if (cv.getBookId() == id) {
                    all = all.add(cv.getSumPrice());
                    buyCartItemVoList.add(cv);
                }
            }
        }
        order.setTotalprice(all);
        //保存
        orderMapper.insert(order);
        //2. 插入明细
        List<Item> items = new ArrayList<>();
        for (Long bid :bookIds){
            //根据bookId 查询出book对象
            Book book = bookService.getById(bid);
            Item item = new Item();
            item.setCreatetime(new Date());
            item.setOrderId(order.getId());
            for (CartItemVo cv :buyCartItemVoList){
                if(bid.equals(cv.getBookId())){
                    item.setBcount(cv.getBuyCount());
                    item.setSumprice(cv.getSumPrice());
                    item.setBookId(bid);
                    break;
                }
            }
            item.setState(1);
            item.setBookName(book.getName());
            item.setPrice(book.getPrice());

            //插入此条明细
            itemMapper.insert(item);
            items.add(item) ;

            //3.更改购买数量
            bookMapper.updateBuyCount(bid,item.getBcount()) ;
            //4. 减库存
            int i = bookMapper.updateStoreCount(bid,item.getBcount());
            if(i == 0 ){
                //return  “库存不足,无法下单” ;
                throw new RuntimeException("库存不足,无法下单!");
            }

            //5.删除购物车中的商品
            redisTemplate.opsForHash().delete(user.getId()+"",bid+"");

            //发送一个 消息
            rabbitTemplate.convertAndSend("cancelOrderExchange","order_routing_key", order.getId()+"");
        }
        //提交事务  返回值通知中 提交


        //回滚事务 ？？？  异常通知中
        return "ok" ;
    }

    @Override
    public Page<OrderVo> getOrderByPage(Integer now, Integer size, String orderNum, Long userid) {
        Page<Order> page = new Page<>(now,size);
        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        if(orderNum != null && !orderNum.trim().equals("")) {
            queryWrapper.eq("orderNum",orderNum);
        }
        queryWrapper.eq("userId",userid);
        queryWrapper.orderByDesc("createtime");
        Page<Order> pageInfo = orderMapper.selectPage(page, queryWrapper);

        Page<OrderVo> pageVo = new Page<>();  //最终返回的数据
        pageVo.setCurrent(pageInfo.getCurrent());
        pageVo.setPages(pageInfo.getPages());
        pageVo.setTotal(pageInfo.getTotal());
        pageVo.setSize(pageInfo.getSize());

        //从pageInfo对象中获取 order的集合
        List<Order> list = pageInfo.getRecords(); // ----> List<OrderVo>
        List<OrderVo> voLists = new ArrayList<>();
        for (Order o :list) {
            OrderVo vo = new OrderVo();
            vo.setId(o.getId());
            vo.setAddressId(o.getAddressId());
            vo.setOrderNum(o.getOrderNum());
            vo.setState(o.getState());
            vo.setUserId(o.getUserId());
            vo.setTotalprice(o.getTotalprice());
            vo.setCreatetime(o.getCreatetime());
            //查询 当前 订单下 所有的 订单明细  根据订单的 ID
            List<CartItemVo> cvs = itemMapper.selectItemByOrdreId(o.getId());
            vo.setLists(cvs);
            voLists.add(vo);
        }
        pageVo.setRecords(voLists) ;
        return pageVo;
    }

    @Override
    @Transactional
    public String cancelOrder(long oid) {
        //根据 订单 id  查询所有的订单明细  （buyCount） 集合

        //循环集合  把购买数量加上去

        return "ok";
    }
}
